_require local "../../../../basis.smi"
_require "../../../libs/ids/main/LocalID.smi"
_require "../../../data/symbols/main/RecordLabel.smi"
_require "../../../data/name/main/CodeLabel.smi"
_require local "../../../extensions/debug/main/Bug.smi"
_require "../../../data/symbols/main/Symbol.smi"
_require "../../../data/symbols/main/Loc.smi"
_require local "../../../data/control/main/Control.smi"
_require "../../../compilerIRs/absyn/main/AbsynConst.smi"
_require "../../../compilerIRs/patterncalc/main/PatternCalc.ppg.smi"
_require "../../../compilerIRs/typedcalc/main/TypedCalc.ppg.smi"
_require "../../../data/runtimetypes/main/FFIAttributes.ppg.smi"
_require "../../../data/types/main/Types.ppg.smi"
_require local "../../../data/types/main/Unify.smi"
_require local "../../../data/types/main/TypesBasics.smi"
_require local "../../../data/builtin/main/BuiltinTypes.smi"
(* _require local "../../../extensions/userlevelprimitive/main/UserLevelPrimitive.smi" *)
_require local "../../../extensions/reflection/main/ReifiedTyData.smi"

structure TypedCalcCon =
struct
  type exp = TypedCalc.tpexp * Types.ty
  type pat = TypedCalc.tppat * Types.ty * Types.varInfo VarID.Map.map

  val TPERROR : exp
  val TPCONSTANT
      : {const:AbsynConst.constant,
         ty:Types.ty,
         loc:Loc.loc}
        -> exp
  val TPSIZEOF
      : Types.ty
        * Loc.loc
        -> exp
  val TPREIFYTY
      : Types.ty
        * Loc.loc
        -> exp
  val TPEXNTAG
      : {exnInfo : Types.exnInfo, loc : Loc.loc}
        -> exp
  val TPEXEXNTAG
      : {exExnInfo : Types.exExnInfo, loc : Loc.loc}
        -> exp
  val TPEXVAR
      : (Types.exVarInfo  * Loc.loc)
        -> exp
  val TPVAR
      : Types.varInfo
        -> exp
  val TPRECFUNVAR
      : {var : Types.varInfo,
         arity : int}
        -> exp
  val TPCAST
      : (exp * Types.ty)
        * Types.ty
        * Loc.loc
        -> exp
  val TPDATACONSTRUCT
      : {con : Types.conInfo,
         instTyList : Types.ty list option,
         argExpOpt : exp option,
         loc : Loc.loc}
        -> exp
  val TPEXNCONSTRUCT
      : {exn : TypedCalc.exnCon,
         argExpOpt : exp option,
         loc : Loc.loc}
        -> exp
  val TPFFIIMPORT_FUN
      : {funExp : exp,
         ffiTy : TypedCalc.ffiTy,
         loc : Loc.loc}
        -> exp
  val TPFFIIMPORT_EXT
      : {funExp : string,
         ffiTy : TypedCalc.ffiTy,
         loc : Loc.loc}
        -> exp
  val TPFOREIGNSYMBOL
      : {name : string,
         ty : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPFOREIGNAPPLY
      : {funExp : exp,
         argExpList : exp list,
         loc : Loc.loc}
        -> exp
  val TPCALLBACKFN
      : {attributes : FFIAttributes.attributes,
         argVarList : Types.varInfo list,
         bodyExp : exp,
         isVoid : bool,
         loc : Loc.loc}
        -> exp
  val TPTAPP
      : {exp : exp,
         instTyList : Types.ty list,
         loc : Loc.loc}
        -> exp
  val TPPOLY
      : {btvEnv : Types.btvEnv,
         constraints : Types.constraint list,
         exp : exp,
         loc : Loc.loc}
        -> exp
  val TPFNM
      : {argVarList : Types.varInfo list,
         bodyExp : exp,
         loc : Loc.loc}
        -> exp
  val TPAPPM
      : {funExp : exp,
         argExpList : exp list,
         loc : Loc.loc}
        -> exp
  val TPCASEM
      : {caseKind : PatternCalc.caseKind,
         expList : exp list,
         ruleList : {args : pat list, body : exp} list,
         loc : Loc.loc}
        -> exp
  val TPSWITCH_CONSTCASE
      : {exp : exp,
         ruleList : {const : AbsynConst.constant,
                     ty : Types.ty,
                     body : exp} list,
         defaultExp : exp,
         loc : Loc.loc}
        -> exp
  val TPSWITCH_CONCASE
      : {exp : exp,
         ruleList : {con : Types.conInfo,
                     instTyList : Types.ty list option,
                     argVarOpt : Types.varInfo option,
                     body : exp} list,
         defaultExp : exp,
         loc : Loc.loc}
        -> exp
  val TPSWITCH_EXNCASE
      : {exp : exp,
         ruleList : {exn : TypedCalc.exnCon,
                     argVarOpt : Types.varInfo option,
                     body : exp} list,
         defaultExp : exp,
         loc : Loc.loc}
        -> exp
  val TPTHROW
      : {catchLabel : FunLocalLabel.id,
         argExpList : exp list,
	 resultTy : Types.ty,
	 loc : Loc.loc}
	-> exp
  val TPCATCH
      : {catchLabel : FunLocalLabel.id,
         argVarList : Types.varInfo list,
         tryExp : exp,
         catchExp : exp,
	 loc : Loc.loc}
        -> exp
  val TPLET
      : {decls : TypedCalc.tpdecl list,
         body : exp,
         loc : Loc.loc}
        -> exp
  val TPMONOLET
      : {binds : (Types.varInfo * exp) list,
         bodyExp : exp,
         loc : Loc.loc}
        -> exp
  val TPRAISE
      : {exp : exp,
         ty : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPHANDLE
      : {exp : exp,
         exnVar : Types.varInfo,
         handler : exp,
         loc : Loc.loc}
        -> exp
  val TPRECORD
      : {fields : exp RecordLabel.Map.map,
         loc : Loc.loc}
        -> exp
  val TPSELECT
      : Types.btvEnv option
        -> {exp : exp,
            label : RecordLabel.label,
            loc : Loc.loc}
        -> exp
  val TPMODIFY
      : Types.btvEnv option
        -> {recordExp : exp,
            label : RecordLabel.label,
            elementExp : exp,
            loc : Loc.loc}
        -> exp
  val TPPRIMAPPLY
      : {primOp : Types.primInfo,
         instTyList : Types.ty list option,
         argExp : exp,
         loc : Loc.loc}
        -> exp
  val TPOPRIMAPPLY
      : {oprimOp : Types.oprimInfo,
         instTyList : Types.ty list,
         argExp : exp,
         loc : Loc.loc}
        -> exp
  val TPJOIN
      : {args : exp * exp,
         ty : Types.ty,
         isJoin:bool,
         loc : Loc.loc}
        -> exp
  val TPDYNAMIC
      : {exp : exp,
         coerceTy : Types.ty,
         elemTy : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPDYNAMICIS
      : {exp : exp,
         coerceTy : Types.ty,
         elemTy : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPDYNAMICVIEW
      : {exp : exp,
         coerceTy : Types.ty,
         elemTy : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPDYNAMICNULL
      : {ty : Types.ty,
         coerceTy : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPDYNAMICTOP
      : {ty : Types.ty,
         coerceTy : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPDYNAMICCASE
      : {groupListTerm : exp,
         groupListTy : Types.ty,
         dynamicTerm : exp,
         dynamicTy : Types.ty,
         elemTy : Types.ty,
         ruleBodyTy : Types.ty,
         loc : Loc.loc}
        -> exp
  val TPDYNAMICEXISTTAPP
      : {existInstMap : exp,
         exp : exp,
         instTyList : Types.ty list,
         loc : Loc.loc}
        -> exp
  val TPPATERROR : pat
  val TPPATCONSTANT
      : AbsynConst.constant
        * Types.ty
        * Loc.loc
        -> pat
  val TPPATVAR
      : Types.varInfo
        -> pat
  val TPPATWILD
      : Types.ty
        * Loc.loc
        -> pat
  val TPPATDATACONSTRUCT
      : {conPat : Types.conInfo,
         instTyList : Types.ty list option,
         argPatOpt : pat option,
         loc : Loc.loc}
        -> pat
  val TPPATEXNCONSTRUCT
      : {exnPat : TypedCalc.exnCon,
         argPatOpt : pat option,
         loc : Loc.loc}
        -> pat
  val TPPATLAYERED
      : {varPat : pat,
         asPat : pat,
         loc : Loc.loc}
        -> pat
  val TPPATRECORD
      : Types.btvEnv option
        -> {fields : pat RecordLabel.Map.map,
           recordTy : Types.ty option,
           loc : Loc.loc}
        -> pat

  val patVars
      : pat list -> Types.varInfo VarID.Map.map

  type env =
      {
        exnEnv : Types.exnInfo ExnID.Map.map,
        exExnEnv : Types.exExnInfo LongsymbolEnv.map,
        varEnv : Types.varInfo VarID.Map.map,
        exVarEnv : Types.exVarInfo LongsymbolEnv.map,
        btvEnv : Types.kind BoundTypeVarID.Map.map
      }

  val emptyEnv : env
  val extendEnv : env * env -> env
  val exnEnv : Types.exnInfo ExnID.Map.map -> env
  val exExnEnv : Types.exExnInfo LongsymbolEnv.map -> env
  val varEnv : Types.varInfo VarID.Map.map -> env
  val exVarEnv : Types.exVarInfo LongsymbolEnv.map -> env
  val btvEnv : Types.kind BoundTypeVarID.Map.map -> env
  val makeExnEnv : Types.exnInfo list -> env
  val makeExExnEnv : Types.exExnInfo list -> env
  val makeVarEnv : Types.varInfo list -> env
  val makeExVarEnv : Types.exVarInfo list -> env
  val clsVarEnv : Types.btvEnv * Types.constraint list
                  -> Types.varInfo list
                  -> env

  val TPEXD
      : Types.exnInfo
        * Loc.loc
        -> TypedCalc.tpdecl * env
  val TPEXNTAGD
      : {exnInfo : Types.exnInfo,
         varInfo : Types.varInfo}
        * Loc.loc
        -> TypedCalc.tpdecl * env
  val TPEXPORTEXN
      : Types.exnInfo
        -> TypedCalc.tpdecl * env
  val TPEXPORTVAR
      : {var : Types.exVarInfo,
         exp : exp}
        -> TypedCalc.tpdecl * env
  val TPEXTERNEXN
      : Types.exExnInfo * Types.provider
        -> TypedCalc.tpdecl * env
  val TPBUILTINEXN
      : Types.exExnInfo
        -> TypedCalc.tpdecl * env
  val TPEXTERNVAR
      : Types.exVarInfo * Types.provider
        -> TypedCalc.tpdecl * env
  val TPFUNDECL
      : {funVarInfo : Types.varInfo,
         ruleList : {args : pat list, body : exp} list} list
        * Loc.loc
        -> TypedCalc.tpdecl * env
  val TPPOLYFUNDECL
      : {btvEnv : Types.btvEnv,
         constraints : Types.constraint list,
         recbinds : {funVarInfo : Types.varInfo,
                     ruleList : {args : pat list, body : exp} list} list,
         loc : Loc.loc}
        -> TypedCalc.tpdecl * env
  val TPVAL
      : (Types.varInfo * exp)
        * Loc.loc
        -> TypedCalc.tpdecl * env
  val TPVALREC
      : {var : Types.varInfo, exp : exp} list
        * Loc.loc
        -> TypedCalc.tpdecl * env
  val TPVALPOLYREC
      : {btvEnv : Types.btvEnv,
         constraints : Types.constraint list,
         recbinds : {var : Types.varInfo, exp : exp} list,
         loc : Loc.loc}
        -> TypedCalc.tpdecl * env

end
